package damas.modelo;

import java.util.LinkedList;
import java.util.List;

import utilidades.ComparableInt;
import utils.IComparable;
import utils.Pair;
import framework.IBasicState;
import framework.IStateAdversary;

/**
 * @author Grupo sin Codigo
 * La representacion del tablero es una matriz de 8x8.
 * 
 */
public class DamasEstado implements IStateAdversary {

	public boolean genereMovidaObligatoria;
	public Pair<Integer, Integer> inicioObligatorio;

	public boolean rojaComioEncadenada;
	public boolean negraComioEncadenada;

	public final int NEGRA = DamasModelo.NEGRA;
	public final int ROJA = DamasModelo.ROJA;
	public final int DAMA = DamasModelo.DAMA;
	private DamasEstado parent;
	private boolean soyMax; // roja
	private boolean soyMin; // negra
	// fichas que quedan en tablero
	private int contadorNegra;
	private int contadorRoja;
	// fichas habilitadas para el movimiento
	protected List<Pair<Integer, Integer>> rojasHabilitadasMovimiento;
	protected List<Pair<Integer, Integer>> negrasHabilitadasMovimiento;
	// posicicones de las fichas en el tablero
	protected List<Pair<Integer, Integer>> posicionesRojas;
	protected List<Pair<Integer, Integer>> posicionesRojasDamas;
	protected List<Pair<Integer, Integer>> posicionesNegrasDamas;
	protected List<Pair<Integer, Integer>> posicionesNegras;
	// fichas obligadas a comer
	protected List<Pair<Integer, Integer>> rojasObligadasAComer;
	protected List<Pair<Integer, Integer>> rojasDamasObligadasAComer;
	protected List<Pair<Integer, Integer>> negrasObligadasAComer;
	protected List<Pair<Integer, Integer>> negrasDamasObligadasAComer;

	private int inicioX;
	private int inicioY;
	private int destinoX;
	private int destinoY;

	private int[][] tablero = new int[][] {
			{ 0, ROJA, 0, ROJA, 0, ROJA, 0, ROJA },
			{ ROJA, 0, ROJA, 0, ROJA, 0, ROJA, 0 },
			{ 0, ROJA, 0, ROJA, 0, ROJA, 0, ROJA }, { 0, 0, 0, 0, 0, 0, 0, 0 },
			{ 0, 0, 0, 0, 0, 0, 0, 0 },
			{ NEGRA, 0, NEGRA, 0, NEGRA, 0, NEGRA, 0 },
			{ 0, NEGRA, 0, NEGRA, 0, NEGRA, 0, NEGRA },
			{ NEGRA, 0, NEGRA, 0, NEGRA, 0, NEGRA, 0 } };

	/**
	 * Meotodo creador Carga las listas con informacion inicial desde el tablero
	 */
	public DamasEstado() {
		this.soyMax = false;
		this.soyMin = true;
		this.contadorNegra = 12;
		this.contadorRoja = 12;
		this.rojasHabilitadasMovimiento = new LinkedList<Pair<Integer, Integer>>();
		this.negrasHabilitadasMovimiento = new LinkedList<Pair<Integer, Integer>>();
		this.posicionesNegras = new LinkedList<Pair<Integer, Integer>>();
		this.posicionesNegrasDamas = new LinkedList<Pair<Integer, Integer>>();
		this.posicionesRojas = new LinkedList<Pair<Integer, Integer>>();
		this.posicionesRojasDamas = new LinkedList<Pair<Integer, Integer>>();
		this.rojasObligadasAComer = new LinkedList<Pair<Integer, Integer>>();
		this.rojasDamasObligadasAComer = new LinkedList<Pair<Integer, Integer>>();
		this.negrasObligadasAComer = new LinkedList<Pair<Integer, Integer>>();
		this.negrasDamasObligadasAComer = new LinkedList<Pair<Integer, Integer>>();
		this.genereMovidaObligatoria = false;
		for (int fila = 0; fila < 3; fila += 2) {
			for (int columna = 0; columna < 8; columna += 2) {
				this.posicionesRojas.add(new Pair<Integer, Integer>(fila,
						columna + 1));
				this.posicionesNegras.add(new Pair<Integer, Integer>(7 - fila,
						columna));
			}
		}
		for (int fila = 1; fila < 2; fila++) {
			for (int columna = 0; columna < 8; columna += 2) {
				this.posicionesRojas.add(new Pair<Integer, Integer>(fila,
						columna));
				this.posicionesNegras.add(new Pair<Integer, Integer>(7 - fila,
						columna + 1));
			}
		}
		actualizaFichasHabilitadasParaMovimiento();
	}

	@Override
	public DamasEstado clone() {
		DamasEstado estadoClon = new DamasEstado();
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {
				estadoClon.tablero[i][j] = this.tablero[i][j];
			}
		}
		estadoClon.soyMax = this.soyMax;
		estadoClon.soyMin = this.soyMin;
		estadoClon.contadorNegra = this.contadorNegra;
		estadoClon.contadorRoja = this.contadorRoja;

		estadoClon.rojasHabilitadasMovimiento.clear();
		for (Pair<Integer, Integer> pair : this.rojasHabilitadasMovimiento) {
			estadoClon.rojasHabilitadasMovimiento
					.add(new Pair<Integer, Integer>(pair.getFirstElem(), pair
							.getSecondElem()));
		}
		estadoClon.negrasHabilitadasMovimiento.clear();
		for (Pair<Integer, Integer> pair : this.negrasHabilitadasMovimiento) {
			estadoClon.negrasHabilitadasMovimiento
					.add(new Pair<Integer, Integer>(pair.getFirstElem(), pair
							.getSecondElem()));
		}
		estadoClon.posicionesNegras.clear();
		for (Pair<Integer, Integer> pair : this.posicionesNegras) {
			estadoClon.posicionesNegras.add(new Pair<Integer, Integer>(pair
					.getFirstElem(), pair.getSecondElem()));
		}
		for (Pair<Integer, Integer> pair : this.posicionesNegrasDamas) {
			estadoClon.posicionesNegrasDamas.add(new Pair<Integer, Integer>(
					pair.getFirstElem(), pair.getSecondElem()));
		}
		estadoClon.posicionesRojas.clear();
		for (Pair<Integer, Integer> pair : this.posicionesRojas) {
			estadoClon.posicionesRojas.add(new Pair<Integer, Integer>(pair
					.getFirstElem(), pair.getSecondElem()));
		}
		for (Pair<Integer, Integer> pair : this.posicionesRojasDamas) {
			estadoClon.posicionesRojasDamas.add(new Pair<Integer, Integer>(pair
					.getFirstElem(), pair.getSecondElem()));
		}
		for (Pair<Integer, Integer> pair : this.rojasObligadasAComer) {
			estadoClon.rojasObligadasAComer.add(new Pair<Integer, Integer>(pair
					.getFirstElem(), pair.getSecondElem()));
		}
		for (Pair<Integer, Integer> pair : this.rojasDamasObligadasAComer) {
			estadoClon.rojasDamasObligadasAComer
					.add(new Pair<Integer, Integer>(pair.getFirstElem(), pair
							.getSecondElem()));
		}
		for (Pair<Integer, Integer> pair : this.negrasObligadasAComer) {
			estadoClon.negrasObligadasAComer.add(new Pair<Integer, Integer>(
					pair.getFirstElem(), pair.getSecondElem()));
		}
		for (Pair<Integer, Integer> pair : this.negrasDamasObligadasAComer) {
			estadoClon.negrasDamasObligadasAComer
					.add(new Pair<Integer, Integer>(pair.getFirstElem(), pair
							.getSecondElem()));
		}
		return estadoClon;
	}

	/**
	 * @return {@link Boolean} true ssi gana Negra
	 */
	@Override
	public boolean minWins() {
		return this.rojasHabilitadasMovimiento.isEmpty()
				|| this.contadorRoja == 0;
	}

	/**
	 * @return {@link Boolean} true ssi gana Roja
	 */
	@Override
	public boolean maxWins() {
		return this.negrasHabilitadasMovimiento.isEmpty()
				|| this.contadorNegra == 0;
	}

	/**
	 * @return {@link Boolean} true ssi soy Max (Rojas)
	 */
	@Override
	public boolean isMax() {
		return this.soyMax;
	}

	/**
	 * @return {@link Boolean} true ssi soy Min (Negras)
	 */
	@Override
	public boolean isMin() {
		return this.soyMin;
	}

	@Override
	public void setMax() {
		this.soyMin = false;
		this.soyMax = true;
	}

	@Override
	public void setMin() {
		this.soyMin = true;
		this.soyMax = false;
	}

	@Override
	public void changeLevel() {
		if (this.isMax()) {
			this.setMin();
		} else {
			this.setMax();
		}
	}

	@Override
	public IComparable evaluate() {
		return new ComparableInt(heuristica());
	}

	/**
	 * Heuristica: Sumo : Damas = 25;ficha comun = 10; fichas C obligadas a
	 * comer = 35; damas obligadas = 45; habilitadas para mover = 40; cantidad
	 * fichas en tablero = 20;fichas adversario = (menos mejor) Resto
	 * (Adversario) : damasA = 3 ; fichasA = 1 ; tiene habilitada para mover = 9
	 * ; tiene ficha obligada a comer = 5 ; tiene damas obligadas a comer = 7;
	 * 
	 * @return {@link Integer}
	 */
	private Integer heuristica() {

		// rojas
		int peonesRojos = (this.contadorRoja - this.posicionesRojasDamas.size());
		int damasRojas = this.posicionesRojasDamas.size();
		int distanciaLineaCoronacionDamaRojos = Heuristica
				.distanciaALineaCoronacion(this.tablero, this.ROJA);
		int peonesASalvoRojos = Heuristica.fichasASalvo(this.tablero,
				this.ROJA, peonesRojos);
		int peonesEnPeligroRojos = peonesRojos - peonesASalvoRojos;
		int damasASalvoRojas = Heuristica.fichasASalvo(this.tablero, this.ROJA
				* this.DAMA, damasRojas);
		int damasEnPeligroRojas = damasRojas - damasASalvoRojas;
		int peonesQueAtacanRojos = Heuristica.fichasQueAtacan(this.tablero,
				this.ROJA);
		int damasQueAtacanRojas = Heuristica.fichasQueAtacan(this.tablero,
				this.ROJA * this.DAMA);
		int peonesMoviblesRojos = this.rojasHabilitadasMovimiento.size()
				- getDamasDeLista(this.rojasHabilitadasMovimiento).size();
		int damasRojasConMovimiento = this.rojasHabilitadasMovimiento.size()
				- peonesMoviblesRojos;
		int camposLibresEnZonaDamasRojas = Heuristica
				.camposLibresEnLineaCoronacion(this.tablero, this.ROJA);
		int piezasQueDefiendenRojas = Heuristica.fichasQueDefienden(
				this.tablero, this.ROJA)
				+ Heuristica.fichasQueDefienden(this.tablero, this.ROJA
						* this.DAMA);
		int peonesEnLineaDiagonalRojos = Heuristica.fichasEnDiagonalPrincipal(
				this.tablero, this.ROJA);
		int damasEnLineaDiagonalRojas = Heuristica.fichasEnDiagonalPrincipal(
				this.tablero, this.ROJA * this.DAMA);
		int peonesEnDiagonalDobleRojos = Heuristica.fichasEnDobleDiagonal(
				this.tablero, this.ROJA);
		int damasEnDiagonalDobleRojas = Heuristica.fichasEnDobleDiagonal(
				this.tablero, this.ROJA * this.DAMA);
		int peonesSolitariosRojos = Heuristica.fichasSolitarias(this.tablero,
				this.ROJA);
		int damasSolitariasRojas = Heuristica.fichasSolitarias(this.tablero,
				this.ROJA * this.DAMA);
		int peonesPosicionadosEnElCentroRojos = Heuristica.cantFichasEnCentro(
				this.tablero, this.ROJA);
		int damasPosicionadasEnElCentroRojas = Heuristica.cantFichasEnCentro(
				this.tablero, this.ROJA * DAMA);
		int camposVaciosRodeadosConRojas = Heuristica
				.camposVaciosRodeadosPorColor(this.tablero, this.ROJA);

		int bloqueoParaDamasRojas = Heuristica.bloqueoParaDamas(this.ROJA,
				this.tablero);
		int peonesProxADamasRojas = Heuristica.peonesProximosADamas(
				this.tablero, this.ROJA);

		// negras
		int peonesNegros = (this.contadorNegra - this.posicionesNegrasDamas
				.size());
		int damasNegras = this.posicionesNegrasDamas.size();
		int distanciaLineaCoronacionDamaNegras = Heuristica
				.distanciaALineaCoronacion(tablero, this.NEGRA);
		int peonesASalvoNegros = Heuristica.fichasASalvo(tablero, this.NEGRA,
				peonesNegros);
		int peonesEnPeligroNegros = peonesNegros - peonesASalvoNegros;
		int damasASalvoNegras = Heuristica.fichasASalvo(tablero, this.NEGRA
				* this.DAMA, damasNegras);
		int damasEnPeligroNegras = damasNegras - damasASalvoNegras;
		int peonesQueAtacanNegros = Heuristica.fichasQueAtacan(tablero,
				this.NEGRA);
		int damasQueAtacanNegras = Heuristica.fichasQueAtacan(this.tablero,
				this.NEGRA * this.DAMA);
		int peonesMoviblesNegros = this.negrasHabilitadasMovimiento.size()
				- getDamasDeLista(this.negrasHabilitadasMovimiento).size();
		int damasNegrasConMovimiento = this.negrasHabilitadasMovimiento.size()
				- peonesMoviblesNegros;
		int camposLibresEnZonaDamasNegras = Heuristica
				.camposLibresEnLineaCoronacion(tablero, this.NEGRA);
		int piezasQueDefiendenNegras = Heuristica.fichasQueDefienden(tablero,
				this.NEGRA)
				+ Heuristica
						.fichasQueDefienden(tablero, this.NEGRA * this.DAMA);
		int peonesEnLineaDiagonalNegros = Heuristica.fichasEnDiagonalPrincipal(
				tablero, this.NEGRA);
		int damasEnLineaDiagonalNegras = Heuristica.fichasEnDiagonalPrincipal(
				tablero, this.NEGRA * this.DAMA);
		int peonesEnDiagonalDobleNegros = Heuristica.fichasEnDobleDiagonal(
				tablero, this.NEGRA);
		int damasEnDiagonalDobleNegras = Heuristica.fichasEnDobleDiagonal(
				tablero, this.NEGRA * this.DAMA);
		int peonesSolitariosNegros = Heuristica.fichasSolitarias(tablero,
				this.NEGRA);
		int damasSolitariasNegras = Heuristica.fichasSolitarias(tablero,
				this.NEGRA * this.DAMA);
		int peonesPosicionadosEnElCentroNegros = Heuristica.cantFichasEnCentro(
				tablero, this.NEGRA);
		int damasPosicionadasEnElCentroNegras = Heuristica.cantFichasEnCentro(
				tablero, this.NEGRA * this.DAMA);
		int camposVaciosRodeadosConNegras = Heuristica
				.camposVaciosRodeadosPorColor(tablero, this.NEGRA);
		int damasRojasEnEsquina = Heuristica.fichasEnEsquinas(tablero,
				this.ROJA * this.DAMA);
		int peonesRojosEnEsquina = Heuristica.fichasEnEsquinas(tablero,
				this.ROJA);
		int damasNegrasEnEsquina = Heuristica.fichasEnEsquinas(tablero,
				this.ROJA * this.DAMA);
		int peonesNegraEnEsquina = Heuristica.fichasEnEsquinas(tablero,
				this.NEGRA);
		int bloqueoParaDamasNegras = Heuristica.bloqueoParaDamas(this.NEGRA,
				tablero);
		int peonesProxADamasNegras = Heuristica.peonesProximosADamas(
				this.tablero, this.NEGRA);

			// coeficientes
			int peones = 2;
			int damas = 6;
			int distanciaCoronacion = 0;
			int peonesASalvo = 10;
			int peonesEnPeligro = 5;
			int damasASalvo = 0;
			int damasEnPeligro = 0;
			int peonesQueAtacan = 1;
			int damasQueAtacan = 0;
			int peonesEnCentro = 2;
			int damasEnCentro = 0;
			int peonesMovibles = 0;
			int damasMovibles = 0;
			int camposLibresZonaDama = 0;// los del enemigo menos los mios
			int piezasQueDefienden = 1;
			int peonesEnDiagonal = 0;
			int peonesEnDiagonal2 = 0;
			int damasEnDiagonal = 0;
			int damasEnDiagonal2 = 0;
			int peonesSolitarios = 0;
			int damasSolitarias = 0;
			int camposVaciosRodeadosPorColor = 0;// los del enemigo menos los mios
			int bloqueoParaDamas = 16;
			int peonesObligadosAComer = 0;
			int damasObligadasAComer = 0;
			int peonesProximosADamas = 0;

		int valRoja = 0;
		int valNegra = 0;
		// roja
		if (soyMax) {
			valRoja += (peonesRojos - peonesNegros) * peones;
			valRoja += (damasRojas - damasNegras) * damas;
			valRoja += (distanciaLineaCoronacionDamaNegras - distanciaLineaCoronacionDamaRojos)
					* distanciaCoronacion;
			valRoja += (peonesASalvoRojos - peonesASalvoNegros) * peonesASalvo;
			valRoja += (damasASalvoRojas - damasASalvoNegras) * damasASalvo;
			valRoja += (peonesQueAtacanRojos - peonesQueAtacanNegros)
					* peonesQueAtacan;
			valRoja += (damasQueAtacanRojas - damasQueAtacanNegras)
					* damasQueAtacan;
			valRoja += (peonesPosicionadosEnElCentroRojos - peonesPosicionadosEnElCentroNegros)
					* peonesEnCentro;
			valRoja += (damasPosicionadasEnElCentroRojas - damasPosicionadasEnElCentroNegras)
					* damasEnCentro;
			valRoja += (peonesMoviblesRojos - peonesMoviblesNegros)
					* peonesMovibles;
			valRoja += (damasRojasConMovimiento - damasNegrasConMovimiento)
					* damasMovibles;
			// mientras mas tiene mi enemigo mejor para mi
			valRoja += (camposLibresEnZonaDamasNegras - camposLibresEnZonaDamasRojas)
					* camposLibresZonaDama;
			valRoja += (piezasQueDefiendenRojas - piezasQueDefiendenNegras)
					* piezasQueDefienden;
			valRoja += (peonesEnLineaDiagonalRojos - peonesEnLineaDiagonalNegros)
					* peonesEnDiagonal;
			valRoja += (peonesEnDiagonalDobleRojos - peonesEnDiagonalDobleNegros)
					* peonesEnDiagonal2;
			valRoja += (damasEnLineaDiagonalRojas - damasEnLineaDiagonalNegras)
					* damasEnDiagonal;
			valRoja += (damasEnDiagonalDobleRojas - damasEnDiagonalDobleNegras)
					* damasEnDiagonal2;
			// es mejor no tener peones solitarios, por comidas encadenadas
			valRoja += (peonesSolitariosNegros - peonesSolitariosRojos)
					* peonesSolitarios;
			valRoja += (damasSolitariasNegras - damasSolitariasRojas)
					* damasSolitarias;
			// ver esta tambien
			valRoja += (camposVaciosRodeadosConNegras - camposVaciosRodeadosConRojas)
					* camposVaciosRodeadosPorColor;
			valRoja += (damasRojasEnEsquina - damasNegrasEnEsquina);
			valRoja += (peonesRojosEnEsquina - peonesNegraEnEsquina);
			valRoja += bloqueoParaDamasRojas * bloqueoParaDamas;

			valRoja += rojasObligadasAComer.size() * peonesObligadosAComer;
			valRoja += rojasDamasObligadasAComer.size() * damasObligadasAComer;
			valRoja += peonesProxADamasRojas * peonesProximosADamas;
			valRoja -= peonesEnPeligroRojos * peonesEnPeligro;
			valRoja -= damasEnPeligroRojas * damasEnPeligro;
			valRoja -= negrasObligadasAComer.size() * peonesObligadosAComer;
			valRoja -= negrasDamasObligadasAComer.size() * damasObligadasAComer;

			System.out.println(valRoja + "|");
			return valRoja;
		}
		// negra
		else {

			valNegra -= (peonesNegros - peonesRojos) * peones;
			valNegra -= (damasNegras - damasRojas) * damas;
			valNegra -= (distanciaLineaCoronacionDamaRojos - distanciaLineaCoronacionDamaNegras)
					* distanciaCoronacion;
			valNegra -= (peonesASalvoNegros - peonesASalvoRojos) * peonesASalvo;
			valNegra -= (damasASalvoNegras - damasASalvoRojas) * damasASalvo;
			valNegra -= (peonesQueAtacanNegros - peonesQueAtacanRojos)
					* peonesQueAtacan;
			valNegra -= (damasQueAtacanNegras - damasQueAtacanRojas)
					* damasQueAtacan;
			valNegra -= (peonesPosicionadosEnElCentroNegros - peonesPosicionadosEnElCentroRojos)
					* peonesEnCentro;
			valNegra -= (damasPosicionadasEnElCentroNegras - damasPosicionadasEnElCentroRojas)
					* damasEnCentro;
			valNegra -= (peonesMoviblesNegros - peonesMoviblesRojos)
					* peonesMovibles;
			valNegra -= (damasNegrasConMovimiento - damasRojasConMovimiento)
					* damasMovibles;
			// ver esta
			valNegra -= (camposLibresEnZonaDamasRojas - camposLibresEnZonaDamasNegras)
					* camposLibresZonaDama;
			valNegra -= (piezasQueDefiendenNegras - piezasQueDefiendenRojas)
					* piezasQueDefienden;
			valNegra -= (peonesEnLineaDiagonalNegros - peonesEnLineaDiagonalRojos)
					* peonesEnDiagonal;
			valNegra -= (peonesEnDiagonalDobleNegros - peonesEnDiagonalDobleRojos)
					* peonesEnDiagonal2;
			valNegra -= (damasEnLineaDiagonalNegras - damasEnLineaDiagonalRojas)
					* damasEnDiagonal;
			valNegra -= (damasEnDiagonalDobleNegras - damasEnDiagonalDobleRojas)
					* damasEnDiagonal2;
			// es mejor no tener peones solitarios , por comidas encadenadas
			valNegra -= (peonesSolitariosRojos - peonesSolitariosNegros)
					* peonesSolitarios;
			valNegra -= (damasSolitariasRojas - damasSolitariasNegras)
					* damasSolitarias;
			// ver esta tambien
			// no me conviene tener campos vacios rodeados con mis fichas ya que
			// mi enemigo puede comer mis fichas encadenadamente
			valNegra -= (camposVaciosRodeadosConRojas - camposVaciosRodeadosConNegras)
					* camposVaciosRodeadosPorColor;
			valNegra -= (damasNegrasEnEsquina - damasRojasEnEsquina);
			valNegra -= (peonesNegraEnEsquina - peonesRojosEnEsquina);
			valNegra -= bloqueoParaDamasNegras * bloqueoParaDamas;

			valNegra -= negrasObligadasAComer.size() * peonesObligadosAComer;
			valNegra -= negrasDamasObligadasAComer.size()
					* damasObligadasAComer;
			valNegra -= peonesProxADamasNegras * peonesProximosADamas;
			valNegra += peonesEnPeligroNegros * peonesEnPeligro;
			valNegra += damasEnPeligroNegras * damasEnPeligro;
			valNegra += rojasObligadasAComer.size() * peonesObligadosAComer;
			valNegra += rojasDamasObligadasAComer.size() * damasObligadasAComer;
			System.out.println("   |" + valNegra);
			return valNegra;
		}
	}

	/**
	 * @return el valor minimo al que puede evaluar un determinado estado :
	 *         {@code IComparable}
	 * @see IComparable
	 */
	@Override
	public IComparable minVal() {
		return new ComparableInt(-15000);
	}

	/**
	 * @return el valor maximo al que puede evaluar un determinado estado :
	 *         {@code IComparable}
	 * @see IComparable
	 */
	@Override
	public IComparable maxVal() {
		return new ComparableInt(15000);
	}

	@Override
	public IBasicState getParent() {
		return this.parent;
	}

	@Override
	public void setParent(IBasicState ibs) {
		this.parent = (DamasEstado) ibs;
	}

	/**
	 * 
	 * @return true sii alguno de los jugadores gano: {@code boolean}
	 */
	@Override
	public boolean isFinal() {
		return success();
	}

	@Override
	public boolean success() {
		return minWins() || maxWins();
	}

	@Override
	public boolean repOk() {
		return true;
	}

	/**
	 * Retorna el tablero del estado
	 * 
	 * @return {@link int[][]}
	 */
	public int[][] getTablero() {
		return this.tablero;
	}

	public int getContadorNegra() {
		return contadorNegra;
	}

	public void setContadorNegra(int contadorNegra) {
		this.contadorNegra = contadorNegra;
	}

	public int getContadorRoja() {
		return contadorRoja;
	}

	public void setContadorRoja(int contadorRoja) {
		this.contadorRoja = contadorRoja;
	}

	public List<Pair<Integer, Integer>> getRojasHabilitadasMovimiento() {
		return rojasHabilitadasMovimiento;
	}

	public List<Pair<Integer, Integer>> getNegrasHabilitadasMovimiento() {
		return negrasHabilitadasMovimiento;
	}

	/**
	 * Parametros validos para realizar el movimiento
	 * 
	 * @param inicio
	 *            {@link Pair}
	 * @param destino
	 *            {@link Pair}
	 * @return {@link Boolean} true ssi comio una ficha
	 */
	public boolean mover(Pair<Integer, Integer> inicio,
			Pair<Integer, Integer> destino) {

		boolean siComi = false;
		int inicioY = inicio.getFirstElem(), inicioX = inicio.getSecondElem();
		int destinoY = destino.getFirstElem(), destinoX = destino
				.getSecondElem();

		int miColor = tablero[inicioY][inicioX];
		this.tablero[destinoY][destinoX] = this.tablero[inicioY][inicioX];
		if (this.seConvierteEnDama(destino)) {
			tablero[destinoY][destinoX] = tablero[destinoY][destinoX] * DAMA;
		}
		this.tablero[inicioY][inicioX] = 0;
		int posMedioY = 0;
		int posMedioX = 0;
		int fichaQueComi = 0;

		// se comio una ficha
		if (Math.abs(inicioX - destinoX) > 1
				|| Math.abs(inicioY - destinoY) > 1) {
			if (miColor == ROJA || miColor == ROJA * DAMA)
				this.contadorNegra--;
			else
				this.contadorRoja--;

			if (this.esPosibleComerArribaIzq(inicio, destino, miColor)) {
				posMedioY = inicioY - 1;
				posMedioX = inicioX - 1;
			}
			if (this.esPosibleComerArribaDer(inicio, destino, miColor)) {
				posMedioY = inicioY - 1;
				posMedioX = inicioX + 1;
			}
			if (this.esPosibleComerAbajoIzq(inicio, destino, miColor)) {
				posMedioY = inicioY + 1;
				posMedioX = inicioX - 1;
			}
			if (this.esPosibleComerAbajoDer(inicio, destino, miColor)) {
				posMedioY = inicioY + 1;
				posMedioX = inicioX + 1;
			}
			fichaQueComi = tablero[posMedioY][posMedioX];
			tablero[posMedioY][posMedioX] = 0;
			siComi = true;
		}
		actulizarListaDeFichas(inicio, destino, miColor, siComi,
				new Pair<Integer, Integer>(posMedioY, posMedioX), fichaQueComi);
		actualizaFichasHabilitadasParaMovimiento();
		return siComi;
	}

	/**
	 * @param inicio
	 * @param destino
	 * @param miColor
	 * @param siComi
	 * @param comido
	 *            (par que se comio)
	 * @param fichaQueComi
	 *            Actualiza las lista de posiciones de las fichas del tablero
	 */
	private void actulizarListaDeFichas(Pair<Integer, Integer> inicio,
			Pair<Integer, Integer> destino, int miColor, boolean siComi,
			Pair<Integer, Integer> comido, int fichaQueComi) {
		boolean comiUnaDama = false;
		boolean seConvirtioEnDama = (destino.getFirstElem() == 0 && miColor == NEGRA)
				|| (destino.getFirstElem() == 7 && miColor == ROJA);
		if (siComi) {
			comiUnaDama = fichaQueComi == ROJA * DAMA
					|| fichaQueComi == NEGRA * DAMA;
		}
		switch (miColor) {
		case ROJA:
			actualizarListas(posicionesRojas, posicionesNegras,
					posicionesRojasDamas, posicionesNegrasDamas, siComi,
					comiUnaDama, seConvirtioEnDama, inicio, destino, comido);
			break;
		case NEGRA:
			actualizarListas(posicionesNegras, posicionesRojas,
					posicionesNegrasDamas, posicionesRojasDamas, siComi,
					comiUnaDama, seConvirtioEnDama, inicio, destino, comido);
			break;
		case ROJA * DAMA:
			actualizarListas(posicionesRojasDamas, posicionesNegras,
					posicionesRojasDamas, posicionesNegrasDamas, siComi,
					comiUnaDama, seConvirtioEnDama, inicio, destino, comido);

			break;
		default:
			actualizarListas(posicionesNegrasDamas, posicionesRojas,
					posicionesNegrasDamas, posicionesRojasDamas, siComi,
					comiUnaDama, seConvirtioEnDama, inicio, destino, comido);
			break;
		}
	}

	/**
	 * @param listaColorFicha
	 * @param listaColorFichaContraria
	 * @param listaColorDama
	 * @param listaColorDamaContraria
	 * @param siComi
	 * @param comiUnaDama
	 * @param seConvirtioEnDama
	 * @param inicio
	 * @param destino
	 * @param comido
	 *            (par que se comio) Generalizacion de la funcion
	 *            [actulizarListaDeFichas]
	 */
	private void actualizarListas(List<Pair<Integer, Integer>> listaColorFicha,
			List<Pair<Integer, Integer>> listaColorFichaContraria,
			List<Pair<Integer, Integer>> listaColorDama,
			List<Pair<Integer, Integer>> listaColorDamaContraria,
			boolean siComi, boolean comiUnaDama, boolean seConvirtioEnDama,
			Pair<Integer, Integer> inicio, Pair<Integer, Integer> destino,
			Pair<Integer, Integer> comido) {

		int indice;
		// si soy dama la voy a querer sacar
		indice = indiceDelParEnLista(listaColorFicha, inicio);
		listaColorFicha.remove(indice);// saco de la lista de color de la ficha
		if (siComi) {
			if (comiUnaDama) {
				indice = indiceDelParEnLista(listaColorDamaContraria, comido);
				listaColorDamaContraria.remove(indice);
			} else {
				indice = indiceDelParEnLista(listaColorFichaContraria, comido);
				listaColorFichaContraria.remove(indice);
			}
		}
		if (seConvirtioEnDama) {
			listaColorDama.add(destino);
		} else {
			listaColorFicha.add(destino);
		}
	}

	/**
	 * @param lista
	 *            {@link LinkedList}
	 * @param par
	 *            {@link Pair}
	 * @return {@link int} con la posicion del elemento en la lista ; -1 ssi no
	 *         existe el elemento
	 */
	private int indiceDelParEnLista(List<Pair<Integer, Integer>> lista,
			Pair<Integer, Integer> par) {
		boolean encontre = false;
		int i;
		if (lista.isEmpty()) {
			return -1;
		} else {
			i = 0;
			while (!encontre && i < lista.size()) {
				encontre = this.sonIgualesLosPares(lista.get(i), par);
				i++;
			}
		}
		return --i;
	}

	/**
	 * @param p1
	 *            {@link Pair}
	 * @param p2
	 *            {@link Pair}
	 * @return True si los pares son iguales
	 */
	private boolean sonIgualesLosPares(Pair<Integer, Integer> p1,
			Pair<Integer, Integer> p2) {
		return (p1.getFirstElem() == p2.getFirstElem() && p1.getSecondElem() == p2
				.getSecondElem());
	}

	/**
	 * @param inicio
	 *            {@link Pair}
	 * @param destino
	 *            {@link Pair}
	 * @return {@link Boolean} true ssi el moviento es SIN comer
	 */
	public boolean esMovimientoSimple(Pair<Integer, Integer> inicio,
			Pair<Integer, Integer> destino) {

		int inicioY = inicio.getFirstElem(), inicioX = inicio.getSecondElem();
		int destinoY = destino.getFirstElem(), destinoX = destino
				.getSecondElem();
		int miColor = tablero[inicioY][inicioX];
		// verifica movimiento (una casilla en diagonal) directo de la dama
		if (miColor == ROJA * DAMA || miColor == NEGRA * DAMA) {
			if (destinoX == inicioX + 1 || destinoX == inicioX - 1) {
				if (destinoY == inicioY + 1 || destinoY == inicioY - 1) {
					return true;
				}
			}
		} else {
			// verifica movimiento (una casilla en diagonal) directo de la ficha
			// diferencia si es roja o negra
			if (miColor == ROJA) {
				if (destinoX == inicioX + 1 || destinoX == inicioX - 1) {
					if (destinoY == inicioY + 1) {
						return true;
					}
				}
			} else {
				if (destinoX == inicioX + 1 || destinoX == inicioX - 1) {
					if (destinoY == inicioY - 1) {
						return true;
					}
				}
			}
		}
		return false;
	}

	/**
	 * @param inicioY
	 *            {@link int} pos medio
	 * @param inicioX
	 *            {@link int} pos medio
	 * @param miColor
	 *            {@link int} El color de mi ficha
	 * @return {@link Boolean} True ssi la ficha que es pasada por parametro es
	 *         distinta a la mia (color), la ficha que voy a comer es del
	 *         contrincante
	 */
	private boolean movimientoComerCorrecto(int inicioY, int inicioX,
			int miColor) {
		if (miColor == ROJA || miColor == ROJA * DAMA) {
			return (tablero[inicioY][inicioX] == NEGRA || tablero[inicioY][inicioX] == NEGRA
					* DAMA);
		} else {
			return (tablero[inicioY][inicioX] == ROJA || tablero[inicioY][inicioX] == ROJA
					* DAMA);
		}
	}

	/**
	 * @param desde
	 *            {@link Pair}
	 * @param hasta
	 *            {@link Pair}
	 * @return true ssi es posible comer la ficha adversaria
	 */
	public boolean movimientoComerFicha(Pair<Integer, Integer> desde,
			Pair<Integer, Integer> hasta) {

		this.inicioY = desde.getFirstElem();
		this.inicioX = desde.getSecondElem();
		this.destinoY = hasta.getFirstElem();
		this.destinoX = hasta.getSecondElem();
		int miColor = tablero[inicioY][inicioX];

		if (miColor == ROJA * DAMA || miColor == NEGRA * DAMA) {
			return this.esPosibleComerArribaIzq(desde, hasta, miColor)
					|| this.esPosibleComerArribaDer(desde, hasta, miColor)
					|| this.esPosibleComerAbajoIzq(desde, hasta, miColor)
					|| this.esPosibleComerAbajoDer(desde, hasta, miColor);
		} else {
			if (miColor == ROJA) {
				return this.esPosibleComerAbajoDer(desde, hasta, miColor)
						|| this.esPosibleComerAbajoIzq(desde, hasta, miColor);
			} else
				return this.esPosibleComerArribaDer(desde, hasta, miColor)
						|| this.esPosibleComerArribaIzq(desde, hasta, miColor);
		}
	}

	/**
	 * @param desde
	 *            {@link Pair}
	 * @param hasta
	 *            {@link Pair}
	 * @param miColor
	 *            {@link int}
	 * @return true ssi puedo comer una ficha que esta abajo a la izq
	 */
	public boolean esPosibleComerAbajoIzq(Pair<Integer, Integer> desde,
			Pair<Integer, Integer> hasta, int miColor) {
		this.inicioY = desde.getFirstElem();
		this.inicioX = desde.getSecondElem();
		this.destinoY = hasta.getFirstElem();
		this.destinoX = hasta.getSecondElem();

		// mueve comiendo en diagonal Izq hacia abajo
		if (destinoX == inicioX - 2 && destinoY == inicioY + 2) {
			return movimientoComerCorrecto(inicioY + 1, inicioX - 1, miColor);
		}
		return false;
	}

	/**
	 * @param desde
	 *            {@link Pair}
	 * @param hasta
	 *            {@link Pair}
	 * @param miColor
	 *            {@link int}
	 * @return true ssi puedo comer una ficha que esta abajo a la der
	 */
	public boolean esPosibleComerAbajoDer(Pair<Integer, Integer> desde,
			Pair<Integer, Integer> hasta, int miColor) {
		this.inicioY = desde.getFirstElem();
		this.inicioX = desde.getSecondElem();
		this.destinoY = hasta.getFirstElem();
		this.destinoX = hasta.getSecondElem();

		// mueve comiendo en diagonal derecha hacia abajo
		if (destinoX == inicioX + 2 && destinoY == inicioY + 2) {
			return movimientoComerCorrecto(inicioY + 1, inicioX + 1, miColor);
		}
		return false;
	}

	/**
	 * @param desde
	 *            {@link Pair}
	 * @param hasta
	 *            {@link Pair}
	 * @param miColor
	 *            {@link int}
	 * @return true ssi puedo comer una ficha que esta arriba a la der
	 */
	public boolean esPosibleComerArribaDer(Pair<Integer, Integer> desde,
			Pair<Integer, Integer> hasta, int miColor) {
		this.inicioY = desde.getFirstElem();
		this.inicioX = desde.getSecondElem();
		this.destinoY = hasta.getFirstElem();
		this.destinoX = hasta.getSecondElem();

		// mueve comiendo en diagonal derecha hacia arriba
		if (destinoX == inicioX + 2 && destinoY == inicioY - 2) {
			return movimientoComerCorrecto(inicioY - 1, inicioX + 1, miColor);
		}
		return false;
	}

	/**
	 * @param desde
	 *            {@link Pair}
	 * @param hasta
	 *            {@link Pair}
	 * @param miColor
	 *            {@link int}
	 * @return true ssi puedo comer una ficha que esta arriba a la izq
	 */
	public boolean esPosibleComerArribaIzq(Pair<Integer, Integer> desde,
			Pair<Integer, Integer> hasta, int miColor) {
		this.inicioY = desde.getFirstElem();
		this.inicioX = desde.getSecondElem();
		this.destinoY = hasta.getFirstElem();
		this.destinoX = hasta.getSecondElem();

		// mueve comiendo en diagonal izquierda hacia arriba
		if (this.destinoX == this.inicioX - 2
				&& this.destinoY == this.inicioY - 2) {
			return movimientoComerCorrecto(this.inicioY - 1, this.inicioX - 1,
					miColor);
		}
		return false;
	}

	/**
	 * @param posicion
	 *            {@link Pair} Es el lugar a donde voy a cambiar la ficha
	 * @param tipoFicha
	 *            {@link int} Es el tipo de la ficha que tengo que poner en esa
	 *            posicion en el tablero
	 */
	public void insertarDama(Pair<Integer, Integer> posicion, int tipoFicha) {
		this.tablero[posicion.getFirstElem()][posicion.getSecondElem()] = tipoFicha;

	}

	public List<Pair<Integer, Integer>> getPosicionesRojas() {
		return posicionesRojas;
	}

	public List<Pair<Integer, Integer>> getPosicionesRojasDamas() {
		return posicionesRojasDamas;
	}

	public List<Pair<Integer, Integer>> getPosicionesNegrasDamas() {
		return posicionesNegrasDamas;
	}

	public List<Pair<Integer, Integer>> getPosicionesNegras() {
		return posicionesNegras;
	}

	/**
	 * @param casilla
	 *            {@link Pair}
	 * @return True ssi la casilla esta dentro del tablero
	 */
	public boolean esCasillaValida(Pair<Integer, Integer> casilla) {
		int posY = casilla.getFirstElem();
		int posX = casilla.getSecondElem();
		return (posY > -1 && posY < 8) && (posX > -1 && posX < 8);
	}

	/**
	 * Actualiza las fichas habilitadas para el movimiento
	 */
	public void actualizaFichasHabilitadasParaMovimiento() {

		LinkedList<Pair<Integer, Integer>> fichasRojas = (LinkedList<Pair<Integer, Integer>>) this
				.getPosicionesRojas();
		LinkedList<Pair<Integer, Integer>> damasRojas = (LinkedList<Pair<Integer, Integer>>) this
				.getPosicionesRojasDamas();
		LinkedList<Pair<Integer, Integer>> fichasNegras = (LinkedList<Pair<Integer, Integer>>) this
				.getPosicionesNegras();
		LinkedList<Pair<Integer, Integer>> damasNegras = (LinkedList<Pair<Integer, Integer>>) this
				.getPosicionesNegrasDamas();

		Pair<Integer, Integer> ficha;

		this.negrasHabilitadasMovimiento.clear();
		this.rojasHabilitadasMovimiento.clear();

		if (!fichasRojas.isEmpty()) {
			for (int i = 0; i < fichasRojas.size(); i++) {
				ficha = fichasRojas.get(i);
				this.cargarListaPosiblesMovimentosAbajo(
						rojasHabilitadasMovimiento, ficha);
			}
		}// mete las damas con con posible mov
		if (!damasRojas.isEmpty()) {
			for (int i = 0; i < damasRojas.size(); i++) {
				ficha = damasRojas.get(i);
				if (!this.cargarListaPosiblesMovimentosAbajo(
						rojasHabilitadasMovimiento, ficha)) {
					this.cargarListaPosiblesMovimentosArriba(
							rojasHabilitadasMovimiento, ficha);
				}
			}
		}
		if (!fichasNegras.isEmpty()) {
			for (int i = 0; i < fichasNegras.size(); i++) {
				ficha = fichasNegras.get(i);
				this.cargarListaPosiblesMovimentosArriba(
						negrasHabilitadasMovimiento, ficha);
			}
		}// mete las damas con con posible mov
		if (!damasNegras.isEmpty()) {
			for (int i = 0; i < damasNegras.size(); i++) {
				ficha = damasNegras.get(i);
				if (!this.cargarListaPosiblesMovimentosAbajo(
						negrasHabilitadasMovimiento, ficha)) {
					this.cargarListaPosiblesMovimentosArriba(
							negrasHabilitadasMovimiento, ficha);
				}
			}
		}
		rojasDamasObligadasAComer();
		rojasObligadasAComer();
		negrasObligadasAComer();
		negrasDamasObligadasAComer();
		;
	}

	/**
	 * @param listaFichashabilitadaMov
	 * @param ficha
	 *            {@link Pair}
	 * @return {@link LinkedList} Lista con la ficha incluida si es posible
	 *         moverla
	 */
	private boolean cargarListaPosiblesMovimentosAbajo(
			List<Pair<Integer, Integer>> listaFichashabilitadaMov,
			Pair<Integer, Integer> ficha) {

		int y = ficha.getFirstElem();
		int x = ficha.getSecondElem();
		int miColor = tablero[y][x];
		boolean metio = false;
		// mov directo
		if ((this.esCasillaValida(new Pair<Integer, Integer>(y + 1, x + 1)) && tablero[y + 1][x + 1] == 0)
				|| (this.esCasillaValida(new Pair<Integer, Integer>(y + 1,
						x - 1)) && tablero[y + 1][x - 1] == 0)) {
			listaFichashabilitadaMov.add(ficha);
			metio = true;
			// tiene movimientos largos ?
		} else {
			if ((this.esCasillaValida(new Pair<Integer, Integer>(y + 2, x + 2))
					&& tablero[y + 2][x + 2] == 0 && this
						.esPosibleComerAbajoDer(ficha,
								new Pair<Integer, Integer>(y + 2, x + 2),
								miColor))
					|| (this.esCasillaValida(new Pair<Integer, Integer>(y + 2,
							x - 2)) && tablero[y + 2][x - 2] == 0 && this
								.esPosibleComerAbajoIzq(
										ficha,
										new Pair<Integer, Integer>(y + 2, x - 2),
										miColor))) {
				metio = true;
				listaFichashabilitadaMov.add(ficha);
			}
		}
		return metio;
	}

	/**
	 * @param listaFichashabilitadaMov
	 * @param ficha
	 *            {@link Pair}
	 * @return {@link LinkedList} Lista con la ficha incluida si es posible
	 *         moverla
	 */
	private boolean cargarListaPosiblesMovimentosArriba(
			List<Pair<Integer, Integer>> listaFichashabilitadaMov,
			Pair<Integer, Integer> ficha) {
		int y = ficha.getFirstElem();
		int x = ficha.getSecondElem();
		int miColor = tablero[y][x];
		boolean metio = false;
		// mov directo
		if ((this.esCasillaValida(new Pair<Integer, Integer>(y - 1, x - 1)) && tablero[y - 1][x - 1] == 0)
				|| (this.esCasillaValida(new Pair<Integer, Integer>(y - 1,
						x + 1)) && tablero[y - 1][x + 1] == 0)) {
			listaFichashabilitadaMov.add(ficha);
			metio = true;
			// tiene movimientos largos ?
		} else {
			if ((this.esCasillaValida(new Pair<Integer, Integer>(y - 2, x + 2))
					&& tablero[y - 2][x + 2] == 0 && this
						.esPosibleComerArribaDer(ficha,
								new Pair<Integer, Integer>(y - 2, x + 2),
								miColor))
					|| (this.esCasillaValida(new Pair<Integer, Integer>(y - 2,
							x - 2)) && tablero[y - 2][x - 2] == 0 && this
								.esPosibleComerArribaIzq(
										ficha,
										new Pair<Integer, Integer>(y - 2, x - 2),
										miColor))) {
				listaFichashabilitadaMov.add(ficha);
				metio = true;
			}
		}
		return metio;
	}

	/**
	 * Actualiza la lista de fichas Rojas obligadas a comer
	 */
	private void rojasObligadasAComer() {
		Pair<Integer, Integer> ficha = new Pair<Integer, Integer>();
		rojasObligadasAComer.clear();
		if (!posicionesRojas.isEmpty()) {
			for (int i = 0; i < posicionesRojas.size(); i++) {
				ficha = posicionesRojas.get(i);
				if (tieneComidaAlcanzable(ficha)) {
					rojasObligadasAComer.add(ficha);
				}
			}
		}
	}

	/**
	 * Actualiza la lista de fichas Rojas Damas obligadas a comer
	 */
	private void rojasDamasObligadasAComer() {
		Pair<Integer, Integer> ficha = new Pair<Integer, Integer>();
		rojasDamasObligadasAComer.clear();
		if (!posicionesRojasDamas.isEmpty()) {
			for (int i = 0; i < posicionesRojasDamas.size(); i++) {
				ficha = posicionesRojasDamas.get(i);
				if (tieneComidaAlcanzable(ficha)) {
					rojasDamasObligadasAComer.add(ficha);
				}
			}
		}
	}

	/**
	 * Actualiza la lista de fichas Negras obligadas a comer
	 */
	private void negrasObligadasAComer() {
		Pair<Integer, Integer> ficha = new Pair<Integer, Integer>();
		negrasObligadasAComer.clear();
		if (!posicionesNegras.isEmpty()) {
			for (int i = 0; i < posicionesNegras.size(); i++) {
				ficha = posicionesNegras.get(i);
				if (tieneComidaAlcanzable(ficha)) {
					negrasObligadasAComer.add(ficha);
				}
			}
		}
	}

	/**
	 * Actualiza la lista de fichas Negras Damas obligadas a comer
	 */
	private void negrasDamasObligadasAComer() {
		Pair<Integer, Integer> ficha = new Pair<Integer, Integer>();
		negrasDamasObligadasAComer.clear();
		if (!posicionesNegrasDamas.isEmpty()) {
			for (int i = 0; i < posicionesNegrasDamas.size(); i++) {
				ficha = posicionesNegrasDamas.get(i);
				if (tieneComidaAlcanzable(ficha)) {
					negrasDamasObligadasAComer.add(ficha);
				}
			}
		}
	}

	/**
	 * @param fichas
	 *            {@link Pair}
	 * @return True ssi la ficha tiene comida alcanzable
	 */
	public boolean tieneComidaAlcanzable(Pair<Integer, Integer> fichas) {
		int y = fichas.getFirstElem();
		int x = fichas.getSecondElem();
		int miColor = this.tablero[fichas.getFirstElem()][fichas
				.getSecondElem()];

		boolean b1 = false, b2 = false, b3 = false, b4 = false;

		Pair<Integer, Integer> posArribaIzq = new Pair<Integer, Integer>(y - 2,
				x - 2);
		Pair<Integer, Integer> posArribaDer = new Pair<Integer, Integer>(y - 2,
				x + 2);
		Pair<Integer, Integer> posAbajoIzq = new Pair<Integer, Integer>(y + 2,
				x - 2);
		Pair<Integer, Integer> posAbajoDer = new Pair<Integer, Integer>(y + 2,
				x + 2);

		if (this.esCasillaValida(posArribaIzq)) {
			b1 = (this.tablero[posArribaIzq.getFirstElem()][posArribaIzq
					.getSecondElem()] == 0
					&& (miColor == NEGRA || miColor == NEGRA * DAMA || miColor == ROJA
							* DAMA) && this.esPosibleComerArribaIzq(fichas,
					posArribaIzq, miColor));
		}
		if (this.esCasillaValida(posArribaDer)) {
			b2 = this.tablero[posArribaDer.getFirstElem()][posArribaDer
					.getSecondElem()] == 0
					&& (miColor == NEGRA || (miColor == NEGRA * DAMA || miColor == ROJA
							* DAMA))
					&& this.esPosibleComerArribaDer(fichas, posArribaDer,
							miColor);
		}
		if (this.esCasillaValida(posAbajoIzq)) {
			b3 = (this.tablero[posAbajoIzq.getFirstElem()][posAbajoIzq
					.getSecondElem()] == 0
					&& (miColor == ROJA || miColor == NEGRA * DAMA || miColor == ROJA
							* DAMA) && this.esPosibleComerAbajoIzq(fichas,
					posAbajoIzq, miColor));
		}
		if (this.esCasillaValida(posAbajoDer)) {
			b4 = (this.tablero[posAbajoDer.getFirstElem()][posAbajoDer
					.getSecondElem()] == 0
					&& (miColor == ROJA || miColor == NEGRA * DAMA || miColor == ROJA
							* DAMA) && this.esPosibleComerAbajoDer(fichas,
					posAbajoDer, miColor));
		}

		return b1 || b2 || b3 || b4;
	}

	public List<Pair<Integer, Integer>> getRojasObligadasAComer() {
		return rojasObligadasAComer;
	}

	public List<Pair<Integer, Integer>> getRojasDamasObligadasAComer() {
		return rojasDamasObligadasAComer;
	}

	public List<Pair<Integer, Integer>> getNegrasObligadasAComer() {
		return negrasObligadasAComer;
	}

	public List<Pair<Integer, Integer>> getNegrasDamasObligadasAComer() {
		return negrasDamasObligadasAComer;
	}

	/**
	 * @param lista
	 *            {@link LinkedList}
	 * @return {@link LinkedList} Con solo las damas de la lista pasada por
	 *         parametro
	 */
	public List<Pair<Integer, Integer>> getDamasDeLista(
			List<Pair<Integer, Integer>> lista) {
		LinkedList<Pair<Integer, Integer>> listaDeDamas = new LinkedList<Pair<Integer, Integer>>();
		boolean esDama = false;
		for (Pair<Integer, Integer> pair : lista) {
			esDama = tablero[pair.getFirstElem()][pair.getSecondElem()] == ROJA
					* DAMA
					|| tablero[pair.getFirstElem()][pair.getSecondElem()] == NEGRA
							* DAMA;
			if (esDama) {
				listaDeDamas.add(pair);
			}
		}
		return listaDeDamas;
	}

	/**
	 * @param casilla
	 *            {@link Pair}
	 * @return True ssi la casilla esta ocupada
	 */
	public boolean hayFichaEnLaCasilla(Pair<Integer, Integer> casilla) {
		return (this.tablero[casilla.getFirstElem()][casilla.getSecondElem()] != 0);
	}

	/**
	 * @param destino
	 *            {@link Pair}
	 * @return true ssi la posicion a donde va la ficha implica convertirse en
	 *         dama
	 */
	public boolean seConvierteEnDama(Pair<Integer, Integer> destino) {
		boolean esRoja = tablero[destino.getFirstElem()][destino
				.getSecondElem()] == this.ROJA;
		boolean esDama = (tablero[destino.getFirstElem()][destino
				.getSecondElem()] == ROJA * DAMA)
				|| (tablero[destino.getFirstElem()][destino.getSecondElem()] == NEGRA
						* DAMA);

		if ((7 == destino.getFirstElem() && esRoja && !esDama)
				|| (0 == destino.getFirstElem() && !esRoja && !esDama)) {
			return true;
		}
		return false;
	}
}
